using System;
using System.IO;
using System.Linq;
using System.Reflection;
using JetBrains.Rider.Unity.Editor;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;

namespace JetBrains.Rider.Unity.Editor
{
    public class PythonScriptOpenAsset
    {
        private static string ourEntryPointTypeName = "JetBrains.Rider.Unity.Editor.PluginEntryPoint";

        private static Assembly ourEditorPluginAssembly;

        public static Assembly EditorPluginAssembly
        {
            get
            {
                if (ourEditorPluginAssembly != null)
                    return ourEditorPluginAssembly;
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                ourEditorPluginAssembly = assemblies.FirstOrDefault(a => a.GetName().Name.Equals("JetBrains.Rider.Unity.Editor.Plugin.Full.Repacked"));
                return ourEditorPluginAssembly;
            }
        }
        
        [OnOpenAsset]
        public static bool OpenTextAsset(int instanceID, int line)
        {
            string path = AssetDatabase.GetAssetPath(instanceID);
            if (!path.EndsWith(".py"))
                return false;

            var openResult = false;
            // reflection for fast OpenFileLineCol, when Rider is started and protocol connection is established
            try
            {
                var assembly = EditorPluginAssembly;
                if (assembly == null) return false;
                var type = assembly.GetType(ourEntryPointTypeName);
                if (type == null) return false;
                var field = type.GetField("OpenAssetHandler", BindingFlags.NonPublic | BindingFlags.Static);
                if (field == null) return false;
                var handlerInstance = field.GetValue(null);
                var method = handlerInstance.GetType()
                    .GetMethod("OnOpenedAsset", new[] {typeof(string), typeof(int), typeof(int)});
                if (method == null) return false;
                var assetFilePath = path;
                if (!string.IsNullOrEmpty(path))
                    assetFilePath = Path.GetFullPath(path);
        
                openResult = (bool) method.Invoke(handlerInstance, new object[] {assetFilePath, line,0});
            }
            catch (Exception e)
            {
                Debug.Log("Unable to do OpenFile to Rider from dll, fallback to com.unity.ide.rider implementation.");
                Debug.LogException(e);
            }

            return openResult;
        }
    }
}